#ifndef _SEER_PROTOCOL_V1_H_
#define _SEER_PROTOCOL_V1_H_

#include <stdint.h>
#include <QtEndian>

#define CMD_CTRL_RELOC          0
#define CMD_CTRL_MOVE_START     1
#define CMD_CTRL_MOVE_STOP      2
#define CMD_NAVI_GO_TARGET      3
#define CMD_NAVI_TARGET_MOVE    4
#define CMD_NAVI_TARGET_TURN    5
#define CMD_NAVI_TARGET_PAUSE   6
#define CMD_NAVI_TARGET_RESUME  7
#define CMD_NAVI_TARGET_CANCEL  8

/**
* 状态查询端口和命令码
*/
#define SEER_API_PORT_STAT  19204               // 状态查询端口
#define CMD_STATE_GET_POSITION   1004           // 获取位置
#define CMD_STATE_GET_BATTERY   1007            // 获取电量
#define CMD_STATE_GET_NAVIGATIONAL_STATE 1020   // 获取导航状态
#define CMD_STATE_GET_CONTROL_AUTHORITY 1060    // 查询当前控制权所有者
#define CMD_MAP_GET_CURRENT     1300            // 获取当前地图
#define CMD_MAP_SITE_INFORMATION 1301           // 获取当前地图中站点信息
#define CMD_STATE_GET_ALARM_STATUS 1050         // 查询机器人报警状态
#define CMD_GET_GPIO_STATUS 1013                // 查询机器人 I/O 数据

/**
* 控制端口和命令码
*/
#define SEER_API_PORT_CTRL  19205
#define CMD_CTRL_RELOCATION 2002                // 重定位
#define CMD_CTRL_OPEN_LOOP_MOVE 2010            // 开环运动
#define CMD_CTRL_STOP_OPEN_LOOP_MOVE 2000       // 停止开环运动


/**
* 导航端口和命令码
*/
#define SEER_API_PORT_NAVI  19206              // 导航端口
#define CMD_NAV_MOVE           3055            // 平动
#define CMD_NAV_ROTATE         3056            // 转动
#define CMD_NAV_FIXED_PATH     3051            // 固定路径导航
#define CMD_NAV_SPECIFY_PATH   3066            // 指定路径导航
#define CMD_NAV_PAUSE           3001           // 暂停导航
#define CMD_NAV_RESUME          3002           // 恢复导航
#define CMD_NAV_CANCEL          3003           // 取消导航

/**
* 配置端口和命令吗
*/
#define SEER_API_PORT_CONF  19207               // 配置端口
#define CMD_GET_CONTROL_AUTHORITY 4005          // 获取控制权
#define CMD_RELEASE_CONTROL_AUTHORITY 4006      // 释放控制权
#define CMD_MAP_DOWNLOAD        4011            // 地图下载
#define CMD_CLEAR_ROBOT_ALARM   4009            // 清除机器人所有报警

/**
* 其他端口和命令码
*/
#define SEER_API_PORT_OTHER  19210
#define CMD_CTRL_SOFT_EMERGENCY_STOP 6004       // 软急停
#define CMD_OTHEAR_DO_SET 6001                  // 设置 DO
/**
* 数据推送端口和命令码
*/
#define SEER_API_PORT_PUSH  19301

/**
 * 日志下载端口
 */
#define RMS_CLIENT_LOG_DOWNLOAD_PORT 19302
#define RMS_CLIENT_CMD_LOG_DOWNLOAD  7001       // 下载日志
#define RMS_CLIENT_CMD_LOG_FILE_CLEAN  7002     // 清理日志

/**
 * 自定义和子任务通信命令码
 */
#define RMS_TASK_YOLO_PORT 19303                // 自定义和子任务通信端口
#define RMS_TASK_START 7003                     // 任务开始
#define RMS_TASK_END 7004                       // 任务结束
#define RMS_TASK_STATUS 7005                    // 任务状态

// 最大重连尝试次数常量
#define MAX_RECONNECT_ATTEMPTS 10               // 最大重连尝试次数

class SeerHeader{
public:
    SeerHeader(){
        m_header = 0x5A;
        m_version = 0x01;
        m_number = 0;
        m_length = 0;
        m_type = 0;
        memset(m_reserved,0, 6);
    }

    uint8_t m_header;
    uint8_t m_version;
    uint16_t m_number;
    uint32_t m_length;
    uint16_t m_type;
    uint8_t m_reserved[6];
};


class SeerData{
public:
    SeerData(){}
    ~SeerData(){}
    int size(){
        return sizeof(SeerHeader) + m_header.m_length;
    }


    int setData(uint16_t type,
                const uint8_t* data = NULL,
                int size = 0,
                uint16_t jsonSize = 0,
                uint16_t number = 0x00,
                uint8_t byte15 = 0){

        m_header.m_header = 0x5A;
        m_header.m_version = 0x01;

        qToBigEndian(type,(uint8_t*)&(m_header.m_type));
        qToBigEndian(number,(uint8_t*)&(m_header.m_number));
        memset(m_header.m_reserved,0,6);

        //把转换后大端uint16_t拆分2个uint8_t.
        uint8_t u0 = (uint8_t)(m_header.m_type & 0xFFu);//取低八位.
        uint8_t u1 = (uint8_t)((m_header.m_type >> 8u) & 0xFFu);
        //保留区把发送的指令，放入0,1位).
        m_header.m_reserved[0] = u0;
        m_header.m_reserved[1] = u1;
        //把json区域长度转换成大端uint6_t,再拆分成两个uint8_t放入保留区2、3位.
        if(jsonSize > 0){
            uint16_t bigJsonSize = 0;
            qToBigEndian(jsonSize,(uint8_t*)&(bigJsonSize));
            uint8_t u2 = (uint8_t)(bigJsonSize & 0xFFu);
            uint8_t u3 = (uint8_t)((bigJsonSize >> 8u) & 0xFFu);
            m_header.m_reserved[2] = u2;
            m_header.m_reserved[3] = u3;
        }
        m_header.m_reserved[4] = byte15;
        if (data != NULL){
            memcpy(m_data, data, size);
        }
        qToBigEndian(size,(uint8_t*)&(m_header.m_length));
        return 16 + size;
    }
private:
    SeerHeader m_header;
    uint8_t m_data[1];
};


#endif
